package com.fanketly.funacg2.data.network

import com.fanketly.funacg2.App
import com.fanketly.funacg2.data.dto.LoginDTO
import com.fanketly.funacg2.data.model.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
import kotlin.coroutines.CoroutineContext
import kotlin.experimental.ExperimentalTypeInference


private interface RetrofitNetworkApi {
    /*用户*/
    @POST("login")
    suspend fun getAuth(@Body loginDTO: LoginDTO): ResponseWithData<Auth>

    @POST("register")
    suspend fun register(@Body loginDTO: LoginDTO): Response

    @GET("isExpires")
    suspend fun isExpires(): Response

    /*音频*/
    @GET(value = "asmr")
    suspend fun getWorks(
        @Query("page") page: Int,
        @Query("pageSize") pageSize: Int,
        @Query("order") order: String,
        @Query("sort") sort: String,
    ): WorkList

    @GET(value = "asmr/recommend")
    suspend fun getRecommend(
    ): WorkList

    @GET(value = "asmr/{id}")
    suspend fun getAudio(@Path("id") id: Int): ArrayList<Children>


    @GET("asmr/tag")
    suspend fun getWorkListByTag(
        @Query("tag") tag: Int,
        @Query("page") page: Int,
        @Query("pageSize") pageSize: Int,
    ): WorkList

    @GET("asmr/search")
    suspend fun getWorkListBySearch(
        @Query("name") name: String,
        @Query("page") page: Int,
        @Query("pageSize") pageSize: Int,
    ): WorkList

    /*分类*/
    @GET("asmr/tags")
    suspend fun getTags(): List<TagListItem>

    /*历史*/
    @GET("history")
    suspend fun getHistory(
        @Query("page") page: Int,
        @Query("pageSize") pageSize: Int,
    ): List<HistoryModel>

    @POST("history/add")
    suspend fun addHistory(@Body historyModel: HistoryModel): Response

    @GET("history/delete/{id}")
    suspend fun deleteHistory(@Path("id") id: Int): Response

    @GET("history/clear")
    suspend fun clearHistory(): Response

    /*收藏*/
    @GET("collect")
    suspend fun getCollect(
        @Query("page") page: Int,
        @Query("pageSize") pageSize: Int,
    ): List<CollectModel>

    @POST("collect/add")
    suspend fun addCollect(@Body collectModel: CollectModel): Response

    @GET("collect/delete/{id}")
    suspend fun deleteCollect(@Path("id") id: Int): Response

    @GET("collect/clear")
    suspend fun clearCollect(): Response

    @GET("collect/isCollect/{asmrId}")
    suspend fun isFavourite(@Path("asmrId") asmrId: Int): Response


}


private fun newOkhttp(timeoutSecond: Long) =
    OkHttpClient.Builder().connectTimeout(timeoutSecond, TimeUnit.SECONDS)
        .readTimeout(timeoutSecond, TimeUnit.SECONDS).writeTimeout(timeoutSecond, TimeUnit.SECONDS)
//            .connectionSpecs(Collections.singletonList(spec))
        .addInterceptor(HttpLoggingInterceptor().apply {
            setLevel(HttpLoggingInterceptor.Level.BODY)
        }).addInterceptor(Interceptor { chain ->
            val original: Request = chain.request()
            val requestBuilder: Request.Builder =
                original.newBuilder().header("Authorization", "Bearer ${App.sToken}")
            val request: Request = requestBuilder.build()
            val response = chain.proceed(request)
            response
        }).build()

private fun newRetrofit(url: String, okHttpClient: OkHttpClient) =
    Retrofit.Builder().baseUrl(url).client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create()).build()
        .create(RetrofitNetworkApi::class.java)

@Singleton
class RetrofitNetwork {
    private val baseUrl = "http://10.0.2.2:8080/api/"

    companion object {
        const val sBaseImageUrl = "http://10.0.2.2:8080/api/cover/"
    }

    //    private val baseUrl = "http://192.168.110.33:8080/api/"
    private var okhttp = newOkhttp(5)
    private var networkApi: RetrofitNetworkApi = newRetrofit(baseUrl, okhttp)

    /*用户*/
    suspend fun getAuth(loginDTO: LoginDTO) = networkApi.getAuth(loginDTO)
    suspend fun register(loginDTO: LoginDTO) = networkApi.register(loginDTO)
    suspend fun isExpires() = networkApi.isExpires()

    /*音频*/
    suspend fun getWorkList(page: Int, pageSize: Int, order: String, sort: String) =
        networkApi.getWorks(page, pageSize, order, sort)

    suspend fun getRecommend() =
        networkApi.getRecommend()

    suspend fun getWorkListByTag(tag: Int, page: Int, pageSize: Int) =
        networkApi.getWorkListByTag(tag, page, pageSize)

    suspend fun getWorkListBySearch(name: String, page: Int, pageSize: Int) =
        networkApi.getWorkListBySearch(name, page, pageSize)

    suspend fun getAudio(id: Int) = networkApi.getAudio(id)

    /*分类*/
    suspend fun getTags() = networkApi.getTags()

    /*历史*/
    suspend fun getHistory(page: Int, pageSize: Int) = networkApi.getHistory(page, pageSize)

    suspend fun addHistory(historyModel: HistoryModel) = networkApi.addHistory(historyModel)
    suspend fun deleteHistory(id: Int) = networkApi.deleteHistory(id)
    suspend fun clearHistory() = networkApi.clearHistory()

    /*收藏*/
    suspend fun getCollect(page: Int, pageSize: Int) = networkApi.getCollect(page, pageSize)

    suspend fun addCollect(collectModel: CollectModel) = networkApi.addCollect(collectModel)
    suspend fun deleteCollect(id: Int) = networkApi.deleteCollect(id)
    suspend fun clearCollect() = networkApi.clearCollect()
    suspend fun isFavourite(id: Int) = networkApi.isFavourite(id)

}


@OptIn(ExperimentalTypeInference::class)
fun <T> flowResult(
    context: CoroutineContext = Dispatchers.IO,
    @BuilderInference block: suspend FlowCollector<T>.() -> Unit,
): Flow<Result<T>> {
    return flow(block).flowOn(context).asResult()
}